package com.snda.lib.http;

import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.DataOutputStream;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.lang.ref.WeakReference;
import java.net.HttpURLConnection;
import java.net.InetSocketAddress;
import java.net.MalformedURLException;
import java.net.Proxy;
import java.net.URL;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.apache.http.HttpEntity;
import org.apache.http.HttpHost;
import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.params.HttpClientParams;
import org.apache.http.conn.params.ConnRouteParams;
import org.apache.http.entity.InputStreamEntity;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.params.BasicHttpParams;
import org.apache.http.params.HttpConnectionParams;
import org.apache.http.params.HttpParams;
import org.apache.http.protocol.HTTP;
import org.apache.http.util.EntityUtils;
import com.snda.lib.util.FileHelper;
import android.content.Context;
import android.database.Cursor;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.net.Uri;
import android.os.SystemClock;
import android.util.Log;

public class HttpUtil {
	public static final int NETTIMEOUT = 6000;

	// ============================================================
	// 错误码相关的错误
	// ============================================================
	// HTTP相关的错误
	public static final int ERROR_SUCCESS = 1;
	public static final int ERROR_SELF_CANCEL = 2; // 手工取消
	public static final int ERROR_INVALID_REQUEST = 100; // 错误的HTTP请求
	public static final int ERROR_INVALID_URL = 101; // 无效的URL
	public static final int ERROR_INVALID_PARAM = 102; // 无效的参数
	public static final int ERROR_CONNECT2NETWORK = 103; // 连接网络出错
	public static final int ERROR_WRITE_FILE = 104; // 文件写入失败
	public static final int ERROR_NET_IO = 105; // 网络IO出错
	public static final int ERROR_SERVER_PACKET = 106; // 服务器返回报文错
	public static final int ERROR_FILE_NOT_EXIST = 107; // 请求的文件不存在
	public static final int ERROR_BITMAP_DECODED_FAILED = 108; // 图片打开失败
	public static final int ERROR_CREATE_FILE = 109; // 创建文件失败
	public static final int ERROR_ALREADY_EXIST = 110; // 已经安装
	public static final int ERROR_UNKNOWN = 200; // 未知错误
	public static final int ERROR_INVALID_SAVE_PATH = 201; // 未知错误
	public static final int ERROR_SERVER_RETURN = 202; // 服务器返回失败
	public static final int ERROR_NO_SPACE = 203; // 磁盘可能没有足够的控件
	public static final int ERROR_NO_NETWORK = 204; // 没有检查到网络
	public static final int ERROR_WAITFOR_WIFI = 205; // 应用自定义错误开始
	public static final int ERROR_APP_ERROR_START = 1000; // 应用自定义错误开始

	public static final String KEY_ERROR_CODE = "errcode";
	public static final String KEY_ERROR_MSG = "errmsg";
	public static final String KEY_EXIST_REASON = "existreason";
	public static final String KEY_PATH = "path";
	public static final String KEY_CONTENT = "content";
	public static final String KEY_TASK_TYPE = "tasktype";

	public static final int TASK_TYPE_INVALID = -1; // 暂未使用的

	public static final int EXIST_FOR_SUCCESS = 0; // 执行成功退出
	public static final int EXIST_FOR_CANCEL = 1; // 下载被取消
	public static final int EXIST_FOR_ERROR = 2; // 下载发生错误
	public int nExistReason = EXIST_FOR_SUCCESS;

	protected int nErrcode = 0;
	protected boolean bExist = false; // 是否要退出，默认是不退出

	protected HashMap<String, String> paramsMap = null; // 用以保存所有的参数对
	protected String strResponse = ""; // 响应报文

	protected WeakReference<Context> mContext;

	// 进度相关的通知
	protected ITaskListener httpTaskListener = null;

	public HttpUtil(Context ctx) {
		mContext = new WeakReference<Context>(ctx);
	}

	public void setListener(ITaskListener listener) {
		this.httpTaskListener = listener;
	}

	/*
	 * 增加Post参数
	 */
	public void addParams(String strParamName, String strParamValue) {
		if (paramsMap == null)
			paramsMap = new HashMap<String, String>();

		paramsMap.put(strParamName, strParamValue);
	}

	public void setExit() {
		bExist = true;
	}

	public String getRequestUrl(String strUrl) {

		String strParamsUrl = getRequestParamsUrl();
		if (strParamsUrl == null
				|| strParamsUrl.trim().equalsIgnoreCase("") == true)
			return strUrl;

		// 根据paramsMap生成访问的URL
		String strResultUrl = strUrl + "?" + strParamsUrl;
		return strResultUrl;
	}

	private String getRequestParamsUrl() {

		// 根据paramsMap生成访问的URL
		String strResultUrl = "";
		if (paramsMap != null) {
			Set<String> keys = paramsMap.keySet();
			boolean first = true;
			for (Iterator<String> itr = keys.iterator(); itr.hasNext();) {
				String key = (String) itr.next();
				String value = paramsMap.get(key);
				if (first) {
					first = false;
				} else {
					strResultUrl += "&";
				}

				if (value == null)
					continue;

				strResultUrl += URLEncoder.encode(key) + "="
						+ URLEncoder.encode(value);
			}
		}
		return strResultUrl;
	}

	public static String openUrl(String strResultUrl) {

		URL requestUrl = null;
		InputStream is = null;

		// 如果URL格式错误
		try {
			requestUrl = new URL(strResultUrl);
		} catch (MalformedURLException e) {
			return null;
		}

		String strResponse = "";
		try {

			HttpURLConnection conn = (HttpURLConnection) requestUrl
					.openConnection();
			conn.setConnectTimeout(HttpUtil.NETTIMEOUT);
			conn.setReadTimeout(HttpUtil.NETTIMEOUT);

			conn.connect();
			is = conn.getInputStream();
			if (is == null) {
				return null;
			}

			BufferedReader breader = new BufferedReader(new InputStreamReader(
					is, "utf8"));
			String strLine = breader.readLine();
			while (strLine != null) {

				strResponse += strLine;
				strLine = breader.readLine();
			}

		} catch (IOException e) {
			return null;
		}

		// 如果流被关闭
		try {
			if (is != null)
				is.close();
		} catch (IOException e) {
			return null;
		}

		return strResponse;
	}

	private HttpURLConnection getHttpConnection(String strResultUrl) {

		// 如果URL格式错误
		HttpURLConnection conn = null;
		try {
			URL requestUrl = new URL(strResultUrl);

			HttpHost httpProxy = getHttpProxy();
			if (httpProxy != null) {
				Proxy proxy = new Proxy(Proxy.Type.HTTP, new InetSocketAddress(
						httpProxy.getHostName(), httpProxy.getPort()));
				conn = (HttpURLConnection) requestUrl.openConnection(proxy);
			} else {
				conn = (HttpURLConnection) requestUrl.openConnection();
			}

			if (conn != null) {
				conn.setConnectTimeout(HttpUtil.NETTIMEOUT);
				conn.setReadTimeout(HttpUtil.NETTIMEOUT);
			}

		} catch (MalformedURLException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}

		return conn;
	}

	/**
	 * 执行HTTP Get请求
	 */
	public Map<String, Object> doGetRequest(String strUrl) {

		// 根据paramsMap生成访问的URL
		String strResultUrl = getRequestUrl(strUrl);
		Log.d("SNLib", "request url:");
		Log.d("SNLib", strResultUrl);

		HashMap<String, Object> resultMap = new HashMap<String, Object>();

		// 网络检测
		ConnectivityManager cm = (ConnectivityManager) mContext.get()
				.getSystemService(Context.CONNECTIVITY_SERVICE);
		if (cm == null) {
			resultMap.put(HttpUtil.KEY_ERROR_CODE, HttpUtil.ERROR_NO_NETWORK);
			resultMap.put(HttpUtil.KEY_EXIST_REASON, EXIST_FOR_ERROR);
			return resultMap;
		}

		// 通知任务开始
		if (this.httpTaskListener != null) {
			this.httpTaskListener.OnBeginTask(strResultUrl, 0, null);
		}

		InputStream is = null;
		try {

			HttpURLConnection conn = getHttpConnection(strResultUrl);

			int nTotalSize = conn.getContentLength();

			// 通知获取的总的大小，上层需要使用
			if (this.httpTaskListener != null) {
				this.httpTaskListener.OnGetSize(nTotalSize);
			}

			is = conn.getInputStream();
			if (is == null) {
				resultMap.put(HttpUtil.KEY_ERROR_CODE,
						HttpUtil.ERROR_CONNECT2NETWORK);
				resultMap.put(HttpUtil.KEY_EXIST_REASON, EXIST_FOR_ERROR);
				return resultMap;
			}

			int nReadFinishedSize = 0;

			BufferedReader breader = new BufferedReader(new InputStreamReader(
					is, "utf8"));
			String strLine = breader.readLine();
			while (strLine != null) {

				if (bExist == true)
					break;

				strResponse += strLine;
				nReadFinishedSize = strResponse.length();

				// 通知进度
				if (this.httpTaskListener != null) {
					this.httpTaskListener.OnNotifyProcess(nReadFinishedSize);
				}

				strLine = breader.readLine();
			}

			if (is != null)
				is.close();

		} catch (IOException e) {
			nExistReason = EXIST_FOR_ERROR;
			nErrcode = HttpUtil.ERROR_NET_IO;
		} finally {

		}

		if (nExistReason == EXIST_FOR_SUCCESS) {

			if (this.httpTaskListener != null) {
				this.httpTaskListener.OnFinishedTask(null);
			}

			resultMap.put(HttpUtil.KEY_ERROR_CODE, HttpUtil.ERROR_SUCCESS);
			resultMap.put(HttpUtil.KEY_CONTENT, strResponse);
		} else {
			resultMap.put(HttpUtil.KEY_ERROR_CODE, HttpUtil.ERROR_NET_IO);
			resultMap.put(HttpUtil.KEY_EXIST_REASON, EXIST_FOR_ERROR);
		}

		return resultMap;
	}

	private void setErrorMap(HashMap<String, Object> resultMap, int nErrorCode) {

		resultMap.put(HttpUtil.KEY_EXIST_REASON, EXIST_FOR_ERROR);
		resultMap.put(HttpUtil.KEY_ERROR_CODE, nErrorCode);

		if (this.httpTaskListener != null) {
			httpTaskListener.OnFailed(nErrorCode);
		}
	}

	/**
	 * @desc 执行HTTP Get请求，下载给定的文件
	 * 
	 * @param strFileUrl
	 *            需要下载的文件的URL
	 * 
	 * @param strSavePath
	 *            下载的文件的保存的路径，如果路径为空，则保存在data/data目录下
	 * 
	 * @param strFileName
	 *            保存的文件的名称
	 * 
	 * @param bContinue
	 *            是否需要断点续传
	 */
	public Map<String, Object> doGetFile(Context context, String strFileUrl,
			String strSavePath, String strFileName, boolean bContinue) {

		HashMap<String, Object> resultMap = new HashMap<String, Object>();
		resultMap.put(HttpUtil.KEY_EXIST_REASON, EXIST_FOR_ERROR);

		// 根据paramsMap生成访问的URL
		String strResultUrl = getRequestUrl(strFileUrl);
		Log.d("SNLib", "request url:");
		Log.d("SNLib", strResultUrl);

		String strOutputFilePath = "";

		// 检查data/data目录下是否存在对应的文件
		StringBuffer strFilePath = new StringBuffer();
		FileOutputStream fos = FileHelper.getOutputStream(context, strSavePath,
				strFileName, bContinue, strFilePath);
		if (fos == null) {
			setErrorMap(resultMap, HttpUtil.ERROR_CREATE_FILE);
			return resultMap;
		}
		strOutputFilePath = strFilePath.toString();

		// 通知任务开始
		if (this.httpTaskListener != null) {
			boolean bStart = this.httpTaskListener.OnStartTask(strResultUrl,
					strOutputFilePath);
			if (bStart == false) {
				setErrorMap(resultMap, HttpUtil.ERROR_WAITFOR_WIFI);
				return resultMap;
			}
		}

		ConnectivityManager cm = (ConnectivityManager) context
				.getSystemService(Context.CONNECTIVITY_SERVICE);
		NetworkInfo ni = cm.getActiveNetworkInfo();
		if (ni == null || !ni.isAvailable()) {
			setErrorMap(resultMap, HttpUtil.ERROR_NO_NETWORK);
			return resultMap;
		}

		// 请求的URL
		InputStream is = null;

		long nTotalSize = 0; // 需要下载的文件的总的大小
		long nLeftToReadSize = 0; // 本次需要从网络中读取的报文数目

		long nReadFinishedSize = 0; // 已经读取的字节数

		try {
			int nBeginRange = 0;
			if (bContinue) {
				nBeginRange = FileHelper.getExistFileSize(context, strSavePath,
						strFileName);
			}

			HttpURLConnection conn = getHttpConnection(strResultUrl);
			conn.setRequestProperty("User-Agent", "sndalib");
			String strByteRange = "bytes=" + nBeginRange + "-";
			conn.setRequestProperty("Range", strByteRange);

			nLeftToReadSize = conn.getContentLength();

			int nCode = conn.getResponseCode();
			// 无效的状态码
			if (nCode == -1) {
				setErrorMap(resultMap, HttpUtil.ERROR_CONNECT2NETWORK);
				return resultMap;
			} // 请求的范围越界，意味着本地的文件已经全部下载完毕
			else if (nCode == 416) {

				// 通知任务开始
				if (this.httpTaskListener != null) {
					this.httpTaskListener.OnAlreadyDownload(nBeginRange,
							strSavePath);

				}

				// 通知程序已经下载到本地，不需要任何下载，可以直接安装
				resultMap.put(HttpUtil.KEY_ERROR_CODE,
						HttpUtil.ERROR_ALREADY_EXIST);
				resultMap.put(HttpUtil.KEY_PATH, strOutputFilePath);
				return resultMap;
			} else if (nCode >= 400 && nCode <= 500) {
				setErrorMap(resultMap, HttpUtil.ERROR_FILE_NOT_EXIST);
				return resultMap;

			} else if (nCode >= 500 && nCode <= 600) {
				setErrorMap(resultMap, HttpUtil.ERROR_SERVER_RETURN);
				return resultMap;
			}
			// 断点续传
			else if (nCode == 206) {
				nTotalSize = nLeftToReadSize + nBeginRange;
			} else if (nCode == 200) {
				nTotalSize = nLeftToReadSize;
			} else {
				setErrorMap(resultMap, HttpUtil.ERROR_SERVER_RETURN);
				return resultMap;
			}

			if (nLeftToReadSize == -1) {
				setErrorMap(resultMap, HttpUtil.ERROR_CONNECT2NETWORK);
				return resultMap;
			}

			// 通知任务开始
			if (this.httpTaskListener != null) {
				this.httpTaskListener.OnGetSize(nTotalSize);
			}

			is = conn.getInputStream();
			if (is == null) {
				setErrorMap(resultMap, HttpUtil.ERROR_NET_IO);
				return resultMap;
			}

			nReadFinishedSize = nBeginRange;

			// 通知任务开始
			if (this.httpTaskListener != null) {
				this.httpTaskListener.OnBeginTask(strResultUrl,
						nReadFinishedSize, strOutputFilePath);
			}

		} catch (IOException e) {
			setErrorMap(resultMap, HttpUtil.ERROR_NET_IO);
			return resultMap;
		}

		byte buf[] = new byte[1024];
		do {
			if (bExist == true) {
				nExistReason = EXIST_FOR_CANCEL;
				break;
			}

			int numread = 0;

			// 失败后尝试的次数为5次。
			int nTryTimes = 0;
			while (nTryTimes < 5) {
				try {
					numread = is.read(buf);
					if (numread <= 0) {
						// 为异常
						if (nLeftToReadSize > 0) {
							nTryTimes++;

							Log.d("SNLib", "try times:" + nTryTimes);
							Log.d("SNLib", strResultUrl);

							SystemClock.sleep(200);
						} else {
							nExistReason = EXIST_FOR_SUCCESS;
							nErrcode = HttpUtil.ERROR_SUCCESS;
							break;
						}
					} else {
						nLeftToReadSize -= numread;
						break;
					}

				} catch (IOException e) {
					nExistReason = EXIST_FOR_ERROR;
					nErrcode = HttpUtil.ERROR_NET_IO;

					Log.d("SNLib", "try times:" + nTryTimes);
					Log.d("SNLib", strResultUrl);

					nTryTimes++;
				}
			}

			if (nTryTimes == 5) {
				nExistReason = EXIST_FOR_ERROR;
				nErrcode = HttpUtil.ERROR_NET_IO;
				break;
			}

			if (numread < 0)
				break;

			// 写文件
			try {
				fos.write(buf, 0, numread);
				nReadFinishedSize += numread;

				// 调用这个函数好后会激活onProgressUpdate()事件
				// 通知进度
				if (this.httpTaskListener != null) {
					this.httpTaskListener.OnNotifyProcess(nReadFinishedSize);
				}

			} catch (IOException e) {
				nExistReason = EXIST_FOR_ERROR;
				nErrcode = HttpUtil.ERROR_NO_SPACE;
				break;
			}

		} while (true);

		try {
			if (is != null)
				is.close();
		} catch (IOException e) {
		}

		// 如果是用户主动取消
		if (nExistReason == EXIST_FOR_CANCEL) {

			if (this.httpTaskListener != null) {
				// httpTaskListener.OnFailed(HttpUtil.ERROR_SELF_CANCEL);
			}
		} else if (nExistReason != EXIST_FOR_SUCCESS) {

			setErrorMap(resultMap, nErrcode);
			return resultMap;

		} else if (nExistReason == EXIST_FOR_SUCCESS) {

			if (nReadFinishedSize != nTotalSize && nTotalSize != -1) {
				setErrorMap(resultMap, HttpUtil.ERROR_NET_IO);
				return resultMap;
			} else {

				// 通知进度
				if (this.httpTaskListener != null) {
					this.httpTaskListener.OnFinishedTask(strOutputFilePath
							.toString());
				}
			}
		}

		resultMap.put(HttpUtil.KEY_ERROR_CODE, HttpUtil.ERROR_SUCCESS);
		resultMap.put(HttpUtil.KEY_PATH, strOutputFilePath);
		return resultMap;
	}

	/*
	 * POST接口
	 * 
	 * @param strUrl 请求的URL地址
	 * 
	 * 参数使用分隔符的形式上传
	 */
	public Map<String, Object> doPostRequest(String strUrl) {

		List<NameValuePair> paramPairs = new ArrayList<NameValuePair>();
		if (paramsMap != null) {
			Set<String> keys = paramsMap.keySet();
			for (Iterator<String> itr = keys.iterator(); itr.hasNext();) {
				String key = (String) itr.next();
				paramPairs.add(new BasicNameValuePair(key, paramsMap.get(key)));
			}
		}

		HttpParams httpParams = new BasicHttpParams();
		HttpConnectionParams.setConnectionTimeout(httpParams,
				HttpUtil.NETTIMEOUT);
		HttpConnectionParams.setSoTimeout(httpParams, HttpUtil.NETTIMEOUT);
		HttpClientParams.setRedirecting(httpParams, true);

		HashMap<String, Object> resultMap = new HashMap<String, Object>();
		try {
			HttpPost httpRequest = new HttpPost(strUrl);

			Log.d("SNLib", "Post request url:");
			Log.d("SNLib", strUrl);

			httpRequest.setEntity(new UrlEncodedFormEntity(paramPairs,
					HTTP.UTF_8));

			DefaultHttpClient httpClient = new DefaultHttpClient(httpParams);
			httpClient.getParams().setBooleanParameter(
					"http.protocol.expect-continue", false);

			HttpHost httpProxy = this.getHttpProxy();
			if (httpProxy != null) {
				httpClient.getParams().setParameter(
						ConnRouteParams.DEFAULT_PROXY, httpProxy);
			}

			HttpResponse response = httpClient.execute(httpRequest);
			if (response != null) {

				// 200返回码表示成功，其余的表示失败
				int iStatusCode = response.getStatusLine().getStatusCode();
				if (iStatusCode == 200) {
					String strContent = EntityUtils.toString(response
							.getEntity());
					resultMap.put(HttpUtil.KEY_ERROR_CODE,
							HttpUtil.ERROR_SUCCESS);
					resultMap.put(HttpUtil.KEY_CONTENT, strContent);
					Log.d("HttpClient", "Post response:" + strContent);
				} else {
					resultMap.put(HttpUtil.KEY_ERROR_CODE,
							HttpUtil.httpCode2Errcode(iStatusCode));
					resultMap.put(HttpUtil.KEY_CONTENT, "服务器返回失败，错误码为:"
							+ iStatusCode);
				}
			}

		} catch (IOException e) {
			resultMap.put(HttpUtil.KEY_ERROR_CODE,
					HttpUtil.ERROR_CONNECT2NETWORK);
			resultMap.put(HttpUtil.KEY_EXIST_REASON, EXIST_FOR_ERROR);
		} catch (Exception e) {
			resultMap.put(HttpUtil.KEY_ERROR_CODE, HttpUtil.ERROR_UNKNOWN);
			resultMap.put(HttpUtil.KEY_EXIST_REASON, EXIST_FOR_ERROR);
		}

		return resultMap;
	}

	/*
	 * POST接口
	 * 
	 * @param strUrl 请求的URL地址
	 * 
	 * 所有的post参数形成a=b&c=0&d=0的格式做为一个单一参数上传
	 */
	public Map<String, Object> doPostRequestWithSingleParams(String strUrl) {

		HashMap<String, Object> resultMap = new HashMap<String, Object>();

		String postParams = getRequestParamsUrl();

		HttpParams httpParams = new BasicHttpParams();
		HttpConnectionParams.setConnectionTimeout(httpParams,
				HttpUtil.NETTIMEOUT);
		HttpConnectionParams.setSoTimeout(httpParams, HttpUtil.NETTIMEOUT);
		HttpClientParams.setRedirecting(httpParams, true);

		try {
			HttpPost httpRequest = new HttpPost(strUrl);

			StringEntity se = new StringEntity(postParams);
			httpRequest.setEntity(se);

			DefaultHttpClient httpClient = new DefaultHttpClient(httpParams);
			httpClient.getParams().setBooleanParameter(
					"http.protocol.expect-continue", false);
			HttpHost httpProxy = this.getHttpProxy();
			if (httpProxy != null) {
				httpClient.getParams().setParameter(
						ConnRouteParams.DEFAULT_PROXY, httpProxy);
			}

			HttpResponse response = httpClient.execute(httpRequest);
			if (response != null) {
				// 200返回码表示成功，其余的表示失败
				int iStatusCode = response.getStatusLine().getStatusCode();
				if (iStatusCode == 200) {
					String strContent = EntityUtils.toString(response
							.getEntity());
					resultMap.put(HttpUtil.KEY_ERROR_CODE,
							HttpUtil.ERROR_SUCCESS);
					resultMap.put(HttpUtil.KEY_CONTENT, strContent);
					Log.d("HttpClient", "Post response:" + strContent);
				} else {
					resultMap.put(HttpUtil.KEY_ERROR_CODE,
							HttpUtil.httpCode2Errcode(iStatusCode));
					resultMap.put(HttpUtil.KEY_CONTENT, "服务器返回失败，错误码为:"
							+ iStatusCode);
				}
			}

		} catch (IOException e) {
			resultMap.put(HttpUtil.KEY_ERROR_CODE,
					HttpUtil.ERROR_CONNECT2NETWORK);
			resultMap.put(HttpUtil.KEY_EXIST_REASON, EXIST_FOR_ERROR);
		} catch (Exception e) {
			resultMap.put(HttpUtil.KEY_ERROR_CODE, HttpUtil.ERROR_UNKNOWN);
			resultMap.put(HttpUtil.KEY_EXIST_REASON, EXIST_FOR_ERROR);
		}

		return resultMap;
	}

	/*
	 * 上传文件
	 * 
	 * @param strUrl 请求的URL地址
	 * 
	 * Post的数据为二进制流
	 */
	public Map<String, Object> doStreamPostRequest(String strUrl,
			byte[] dataStream) {

		HashMap<String, Object> resultMap = new HashMap<String, Object>();

		HttpParams httpParams = new BasicHttpParams();
		HttpConnectionParams.setConnectionTimeout(httpParams,
				HttpUtil.NETTIMEOUT);
		HttpConnectionParams.setSoTimeout(httpParams, HttpUtil.NETTIMEOUT);
		HttpClientParams.setRedirecting(httpParams, true);

		String strEnd = "\r\n";
		String strPrefix = "--";
		String strBoundary = "--BOUNDARY_"
				+ java.util.UUID.randomUUID().toString();

		try {
			URL url = new URL(strUrl);

			HttpURLConnection conn = null;

			HttpHost httpProxy = getHttpProxy();
			if (httpProxy != null) {
				Proxy proxy = new Proxy(Proxy.Type.HTTP, new InetSocketAddress(
						httpProxy.getHostName(), httpProxy.getPort()));

				conn = (HttpURLConnection) url.openConnection(proxy);
			} else {
				conn = (HttpURLConnection) url.openConnection();
			}

			conn.setDoInput(true);
			conn.setDoOutput(true);
			conn.setUseCaches(false);

			conn.setRequestMethod("POST");
			conn.setRequestProperty("Connection", "Keep-Alive");
			conn.setRequestProperty("Charset", "UTF-8");
			conn.setRequestProperty("Content-Type",
					"multipart/form-data;boundary=" + strBoundary);

			StringBuilder sb = new StringBuilder();

			/*
			 * 写入普通的参数
			 */
			if (paramsMap != null) {
				for (Map.Entry<String, String> entry : paramsMap.entrySet()) {// 构建表单字段内容
					sb.append(strPrefix);
					sb.append(strBoundary);
					sb.append(strEnd);
					sb.append("Content-Disposition: form-data; name=\""
							+ entry.getKey() + "\"" + strEnd + strEnd);
					sb.append(entry.getValue());
					sb.append(strEnd);
				}
			}

			DataOutputStream ds = new DataOutputStream(conn.getOutputStream());
			ds.write(sb.toString().getBytes());

			/*
			 * 上传文件部分
			 */
			ds.writeBytes(strPrefix + strBoundary + strEnd);
			ds.writeBytes("Content-Disposition:form-data;name=\"name\";"
					+ "filename=\"" + "data" + "\"\r\n");
			ds.writeBytes(strEnd);

			ByteArrayInputStream byteInputStream = new ByteArrayInputStream(
					dataStream);

			int bufferSize = 2048;
			byte[] buffer = new byte[bufferSize];

			int length = -1;
			while ((length = byteInputStream.read(buffer)) != -1) {
				ds.write(buffer, 0, length);
			}

			ds.writeBytes(strEnd);
			ds.writeBytes(strPrefix + strBoundary + strEnd);

			byteInputStream.close();
			ds.flush();

			InputStream is = conn.getInputStream();

			int ch;
			StringBuilder sbResponse = new StringBuilder();
			while ((ch = is.read()) != -1) {
				sbResponse.append((char) ch);
			}

			resultMap.put(HttpUtil.KEY_ERROR_CODE, HttpUtil.ERROR_SUCCESS);
			resultMap.put("content", sbResponse.toString());

			return resultMap;

		} catch (IOException e) {
			resultMap.put(HttpUtil.KEY_ERROR_CODE,
					HttpUtil.ERROR_CONNECT2NETWORK);
			e.printStackTrace();

		} catch (Exception e) {
			resultMap.put(HttpUtil.KEY_ERROR_CODE, HttpUtil.ERROR_UNKNOWN);
			e.printStackTrace();
		}

		return resultMap;
	}

	/*
	 * 上传文件
	 * 
	 * @param strUrl 请求的URL地址
	 * 
	 * Post的数据为二进制流
	 */

	private static String readInputStream(InputStream is) {
		BufferedReader br = new BufferedReader(new InputStreamReader(is), 8192);
		StringBuilder sb = new StringBuilder();
		String s;
		try {
			while ((s = br.readLine()) != null) {
				sb.append(s);
			}
			return sb.toString();
		} catch (IOException e) {
			e.printStackTrace();
		} finally {
			try {
				br.close();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
		return null;
	}

	public Map<String, Object> doPostStreamRequest(String strUrl,
			byte[] dataStream) {

		HashMap<String, Object> resultMap = new HashMap<String, Object>();

		BasicHttpParams basicHttpParams = new BasicHttpParams();
		HttpConnectionParams.setConnectionTimeout(basicHttpParams, 20000);
		HttpConnectionParams.setSoTimeout(basicHttpParams, 30000);
		DefaultHttpClient httpClient = new DefaultHttpClient(basicHttpParams);
		HttpPost httpPost = new HttpPost(strUrl);

		InputStreamEntity isEntity = new InputStreamEntity(
				new ByteArrayInputStream(dataStream), dataStream.length);
		httpPost.setEntity(isEntity);

		HttpHost httpProxy = this.getHttpProxy();
		if (httpProxy != null) {
			httpClient.getParams().setParameter(ConnRouteParams.DEFAULT_PROXY,
					httpProxy);
		}

		try {
			HttpResponse httpResponse = httpClient.execute(httpPost);

			if (httpResponse.getStatusLine().getStatusCode() == 200) {

				HttpEntity httpEntity = httpResponse.getEntity();
				String respContent = readInputStream(httpEntity.getContent());
				if (respContent != null) {

					resultMap.put(HttpUtil.KEY_ERROR_CODE,
							HttpUtil.ERROR_SUCCESS);
					resultMap.put("content", respContent.toString());
					return resultMap;

				}
			}
		} catch (ClientProtocolException e) {
			e.printStackTrace();
		} catch (IOException e) {
			resultMap.put(HttpUtil.KEY_ERROR_CODE,
					HttpUtil.ERROR_CONNECT2NETWORK);
			e.printStackTrace();
		} catch (Exception e) {
			resultMap.put(HttpUtil.KEY_ERROR_CODE, HttpUtil.ERROR_UNKNOWN);
			e.printStackTrace();
		}

		return resultMap;
	}

	/*
	 * 上传文件
	 * 
	 * @param strUrl 请求的URL地址
	 * 
	 * @param strFilePath 需要上传的照片的本地路径
	 * 
	 * 进行POST请求，在PostRequest之前，必须调用addParams增加Post参数
	 */
	public Map<String, Object> doFilePostRequest(String strUrl,
			String strFilePath) {

		HashMap<String, Object> resultMap = new HashMap<String, Object>();

		List<NameValuePair> paramPairs = new ArrayList<NameValuePair>();

		if (paramsMap != null) {
			Set<String> keys = paramsMap.keySet();
			for (Iterator<String> itr = keys.iterator(); itr.hasNext();) {
				String key = (String) itr.next();
				paramPairs.add(new BasicNameValuePair(key, paramsMap.get(key)));
			}
		}

		HttpParams httpParams = new BasicHttpParams();
		HttpConnectionParams.setConnectionTimeout(httpParams,
				HttpUtil.NETTIMEOUT);
		HttpConnectionParams.setSoTimeout(httpParams, HttpUtil.NETTIMEOUT);
		HttpClientParams.setRedirecting(httpParams, true);

		String strEnd = "\r\n";
		String strPrefix = "--";
		String strBoundary = "--BOUNDARY_"
				+ java.util.UUID.randomUUID().toString();

		try {
			URL url = new URL(strUrl);
			HttpURLConnection conn = (HttpURLConnection) url.openConnection();
			conn.setDoInput(true);
			conn.setDoOutput(true);
			conn.setUseCaches(false);

			conn.setRequestMethod("POST");
			conn.setRequestProperty("Connection", "Keep-Alive");
			conn.setRequestProperty("Charset", "UTF-8");
			conn.setRequestProperty("Content-Type",
					"multipart/form-data;boundary=" + strBoundary);

			StringBuilder sb = new StringBuilder();

			/*
			 * 写入普通的参数
			 */
			for (Map.Entry<String, String> entry : paramsMap.entrySet()) {// 构建表单字段内容
				sb.append(strPrefix);
				sb.append(strBoundary);
				sb.append(strEnd);
				sb.append("Content-Disposition: form-data; name=\""
						+ entry.getKey() + "\"" + strEnd + strEnd);
				sb.append(entry.getValue());
				sb.append(strEnd);
			}

			DataOutputStream ds = new DataOutputStream(conn.getOutputStream());
			ds.write(sb.toString().getBytes());

			/*
			 * 上传文件部分
			 */
			boolean bExist = FileHelper.isExistFile(strFilePath);
			if (bExist == true) {

				ds.writeBytes(strPrefix + strBoundary + strEnd);
				ds.writeBytes("Content-Disposition:form-data;name=\"name\";"
						+ "filename=\"" + strFilePath + "\"\r\n");
				ds.writeBytes(strEnd);

				FileInputStream fInputStream = new FileInputStream(strFilePath);

				int bufferSize = 2048;
				byte[] buffer = new byte[bufferSize];

				int length = -1;
				while ((length = fInputStream.read(buffer)) != -1) {
					ds.write(buffer, 0, length);
				}

				ds.writeBytes(strEnd);
				ds.writeBytes(strPrefix + strBoundary + strEnd);

				fInputStream.close();
				ds.flush();
			}

			InputStream is = conn.getInputStream();

			int ch;
			StringBuilder sbResponse = new StringBuilder();
			while ((ch = is.read()) != -1) {
				sbResponse.append((char) ch);
			}

			resultMap.put(HttpUtil.KEY_ERROR_CODE, HttpUtil.ERROR_SUCCESS);
			resultMap.put("content", sbResponse.toString());

			return resultMap;

		} catch (IOException e) {
			resultMap.put(HttpUtil.KEY_ERROR_CODE,
					HttpUtil.ERROR_CONNECT2NETWORK);
			e.printStackTrace();

		} catch (Exception e) {
			resultMap.put(HttpUtil.KEY_ERROR_CODE, HttpUtil.ERROR_UNKNOWN);
			e.printStackTrace();
		}

		return resultMap;
	}

	public HttpHost getHttpProxy() {

		if (mContext == null || mContext.get() == null)
			return null;

		HttpHost httpHost = null;
		try {
			ConnectivityManager cm = (ConnectivityManager) mContext.get()
					.getSystemService(Context.CONNECTIVITY_SERVICE);
			NetworkInfo netInfo = cm.getActiveNetworkInfo();
			if (netInfo != null && netInfo.isAvailable()) {
				String typeName = netInfo.getTypeName();
				String extra = netInfo.getExtraInfo();
				if (typeName.equalsIgnoreCase("MOBILE")) {

					if (extra != null) {
						if (extra.toLowerCase().startsWith("cmwap")
								|| extra.toLowerCase().startsWith("uniwap")
								|| extra.toLowerCase().startsWith("3gwap")) {
							httpHost = new HttpHost("10.0.0.172", 80);
						} else if (extra.startsWith("#777")) {
							Uri apn_uri = Uri
									.parse("content://telephony/carriers/preferapn");
							Cursor c = mContext.get().getContentResolver()
									.query(apn_uri, null, null, null, null);
							if (null != c && c.getCount() > 0) {
								c.moveToFirst();
								String ctapn = c.getString(c
										.getColumnIndex("user"));
								if (ctapn != null && !ctapn.equals("")) {
									if (ctapn.startsWith("ctwap")) {
										httpHost = new HttpHost("10.0.0.200",
												80);
									} else if (ctapn.toLowerCase().startsWith(
											"wap")) {
										httpHost = new HttpHost("10.0.0.200",
												80);
									}
								}
							}
							if (c != null) {
								c.close();
								c = null;
							}
						}
					}
				} else if (typeName.equalsIgnoreCase("WIFI")
						|| typeName.equalsIgnoreCase("WI FI")) {
				}
			}
		} catch (Exception e) {
			httpHost = null;
		}
		return httpHost;
	}

	public static String getErrorDesc(int nErrorCode) {
		switch (nErrorCode) {
		case ERROR_SUCCESS:
			return "success";

		case ERROR_SELF_CANCEL:
			return "手工取消";

		case ERROR_INVALID_URL:
			return "请求的URL无效";

		case ERROR_INVALID_PARAM:
			return "输入参数无效";

		case ERROR_CONNECT2NETWORK:
			return "无法连接网络";

		case ERROR_WRITE_FILE:
			return "文件写入失败，您的SD卡可能无法使用";

		case ERROR_NET_IO:
			return "网络读写失败";

		case ERROR_SERVER_PACKET:
			return "服务器返回报文错误";

		case ERROR_SERVER_RETURN:
			return "服务器返回错误";

		case ERROR_UNKNOWN:
			return "系统内部错误";

		case ERROR_FILE_NOT_EXIST:
			return "请求的文件不存在";

		case ERROR_NO_SPACE:
			return "SD卡可能没有足够的空间";

		case ERROR_BITMAP_DECODED_FAILED:
			return "图片打开失败，可能图片路径不存在或者格式错误";

		}

		return "未知的异常错误";
	}

	public static int httpCode2Errcode(int nHttpCode) {
		switch (nHttpCode) {
		case 300:
		case 301:
		case 400:
		case 401:
		case 402:
		case 403:
		case 404:
		case 405:
		case 406:
		case 407:
		case 408:
		case 409:
		case 410:
		case 500:
		case 501:
		case 502:
		case 503:
			return ERROR_INVALID_URL;

		default:
			return ERROR_INVALID_REQUEST;
		}
	}
}
